#pragma once

#include <cassert>
#include <iostream>
#include <mutex>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

using pageID = size_t;

static const size_t FREE_LIST_NUM = 208;
static const size_t MAX_BYTES = 256 * 1024;
static const size_t PAGE_NUM = 129;

static void *&ObjNext(void *obj) { return *(void **)obj; }

class SizeClass {
  public:
    static size_t RoundUp(size_t size) {
        if (size <= 128) {
            return _RoundUp(size, 8);
        } else if (size <= 1024) {
            return _RoundUp(size, 16);
        } else if (size < 8 * 1024) {
            return _RoundUp(size, 128);
        } else if (size < 64 * 1024) {
            return _RoundUp(size, 1024);
        } else if (size < 256 * 1024) {
            return _RoundUp(size, 8 * 1024);
        } else {
            assert(false);
            return -1;
        }
    }

    // 计算映射的哪一个自由链表桶
    static inline size_t Index(size_t size) {
        assert(size <= MAX_BYTES);

        // 每个区间有多少个链
        static int group_array[4] = {16, 56, 56, 56};
        if (size <= 128) {           // [1,128] 8B -->8B就是2^3B，对应二进制位为3位
            return _Index(size, 3);  // 3是指对齐数的二进制位位数，这里8B就是2^3B，所以就是3
        } else if (size <= 1024) {   // [128+1,1024] 16B -->4位
            return _Index(size - 128, 4) + group_array[0];
        } else if (size <= 8 * 1024) {  // [1024+1,8*1024] 128B -->7位
            return _Index(size - 1024, 7) + group_array[1] + group_array[0];
        } else if (size <= 64 * 1024) {  // [8*1024+1,64*1024] 1024B -->10位
            return _Index(size - 8 * 1024, 10) + group_array[2] + group_array[1] + group_array[0];
        } else if (size <= 256 * 1024) {  // [64*1024+1,256*1024] 8 * 1024B  -->13位
            return _Index(size - 64 * 1024, 13) + group_array[3] + group_array[2] + group_array[1] + group_array[0];
        } else {
            assert(false);
        }
        return -1;
    }

    static size_t NumMoveSize(size_t size) {
        assert(size > 0);

        int num = MAX_BYTES / size;
        if (num > 512) {
            num = 512;
        }
        if (num < 2) {
            num = 2;
        }
        return num;
    }

  private:
    static size_t _RoundUp(size_t size, size_t alignNum) { return ((size + alignNum - 1) & ~(alignNum - 1)); }

    // 求size对应在哈希表中的下标
    static inline size_t _Index(size_t size,
                                size_t align_shift) { /*这里align_shift是指对齐数的二进制位数。比如size为2的时候对齐数
                                                      为8，8就是2^3，所以此时align_shift就是3*/
        return ((size + (1 << align_shift) - 1) >> align_shift) - 1;
        //这里_Index计算的是当前size所在区域的第几个下标，所以Index的返回值需要加上前面所有区域的哈希桶的个数
    }
};

class FreeList {
  public:
    bool Empty() const { return _freeList == nullptr; }

    void Push(void *obj) {
        assert(obj);

        ObjNext(obj) = _freeList;
        _freeList = obj;
    }

    void *Pop() {
        assert(_freeList);

        void *obj = _freeList;
        _freeList = ObjNext(obj);
        return obj;
    }

    size_t &MaxSize() { return _maxSize; }

  private:
    void *_freeList{nullptr};
    size_t _maxSize{1};
};

struct Span {
  public:
    pageID _pageId{0};
    size_t _n{0};

    Span *_next{nullptr};
    Span *_prev{nullptr};

    void *_freeList{nullptr};
    size_t _useCount{0};
};

class SpanList {
  public:
    SpanList() {
        _head = new Span();
        _head->_next = _head;
        _head->_prev = _head;
    }

    void Insert(Span *pos, Span *ptr) {
        assert(pos);
        assert(ptr);

        Span *prev = pos->_prev;

        prev->_next = ptr;
        ptr->_prev = prev;

        ptr->_next = pos;
        pos->_prev = ptr;
    }

    void Erase(Span *pos) {
        assert(pos);
        assert(pos != _head);

        Span *prev = pos->_prev;
        Span *next = pos->_next;

        prev->_next = next;
        next->_prev = prev;
    }

    Span *Begin() { return _head->_next; }

    Span *End() { return _head; }

  private:
    Span *_head{nullptr};
    std::mutex _mtx;
};